# -*- coding: utf-8 -*-

import os
import sys
import random


from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import Qt, SIGNAL, QFileInfo, QProcess, QString
from PyQt4.QtGui import QApplication, QWidget, QIcon, QAction, QFileDialog

from core import songmanager
from core.song import Song
from core.songmanager import SongManager
from ui.main_ui import MainUI
from ui.about_ui import _fromUtf8
from ui.lyrics_ui import Lyrics_UI
from util import tool


class MusicPlayer(QWidget, MainUI):
    def __init__(self, parent=None):
        super(MusicPlayer, self).__init__()
        self.isPlaying = False
        self.isPause = False
        self.isShuffle = False
        self.isLoop = False
        self.playIndex = 0
        self.initUi()    # 初始化界面
        self.initMenu()  # 初始化菜单
        self.initData()  # 初始化数据

    def initUi(self):
        """初始化界面"""
        self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
        self.setWindowIcon(QtGui.QIcon('images/music.png'))
        self.setWindowTitle(u"音乐播放器")

        self.addElements(self)

        self.btnmini.setToolTip(QString(u'<font color="#ffffff" size = 4>最小化</font>'))
        self.connect(self.btnmini, SIGNAL('clicked()'), self.showMinimized)

        self.btnclose.setToolTip(QString(u'<font color="#ffffff" size = 4>关闭</font>'))
        self.connect(self.btnclose, SIGNAL('clicked()'), self.hideWindows)

        self.btnplay.setToolTip(QString(u'<font color="#ffffff" size = 4>点击播放</font>'))
        self.connect(self.btnplay, SIGNAL('clicked()'), self.playOrPause)

        self.btnstop.setToolTip(QString(u'<font color="#ffffff" size = 4>停止</font>'))
        self.connect(self.btnstop, SIGNAL('clicked()'), self.stop)

        self.btnprev.setToolTip(QString(u'<font color="#ffffff" size = 4>播放上一首</font>'))
        self.connect(self.btnprev, SIGNAL('clicked()'), self.playPrev)

        self.btnnext.setToolTip(QString(u'<font color="#ffffff" size = 4>播放下一首</font>'))
        self.connect(self.btnnext, SIGNAL('clicked()'), self.playNext)

        self.btnshuffle.setToolTip(QString(u'<font color="#ffffff" size = 4>随机播放</font>'))
        self.connect(self.btnshuffle, SIGNAL('clicked()'), self.shuffle)

        self.btnloop.setToolTip(QString(u'<font color="#ffffff" size = 4>单曲循环</font>'))
        self.connect(self.btnloop, SIGNAL('clicked()'), self.loop)

        self.btnadd.setToolTip(QString(u'<font color="#ffffff" size = 4>添加歌曲</font>'))
        self.connect(self.btnadd, SIGNAL('clicked()'), self.addFromDialog)

        self.btndel.setToolTip(QString(u'<font color="#ffffff" size = 4>删除歌曲</font>'))
        self.connect(self.btndel, SIGNAL('clicked()'), self.delete)

        self.btn_desk_irc.setToolTip(QString(u'<font color="#ffffff" size = 4>显示歌词</font>'))
        self.connect(self.btn_desk_irc, SIGNAL('clicked()'), self.showOrDismissLyrics)

        self.desk_irc = Lyrics_UI()
        self.desk_irc.show()

        self.list_songs.mouseDoubleClickEvent = self.musicPlay
        self.list_songs.setSelectionRectVisible(True)
        self.list_songs.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        # 添加列表右键菜单
        self.list_songs.setContextMenuPolicy(Qt.CustomContextMenu)
        self.list_songs.customContextMenuRequested[QtCore.QPoint].connect(self.menuRequested)

        self.setAcceptDrops(True) # 支持外拖歌曲

        # 设置系统托盘菜单
        self.trayIcon = QtGui.QSystemTrayIcon()
        self.trayIcon.setIcon(QIcon("images/headset.png"))
        self.trayIcon.setToolTip(u"音乐播放器")
        self.trayIconMenu = QtGui.QMenu(self)

        self.aboutAction = QtGui.QAction(u"关于", self, triggered=self.showAboutDialog)
        self.quitAction = QtGui.QAction(u"退出", self, triggered=self.closeWindows)
        self.shuffleAction = QtGui.QAction(u"随机播放", self, triggered=self.shuffle)
        self.repeat1Action = QtGui.QAction(u"单曲循环", self, triggered=self.loop)
        self.repeatAction = QtGui.QAction(u"列表循环", self, triggered=self.repeat)
        self.shuffleAction.setCheckable(True)
        self.repeat1Action.setCheckable(True)
        self.repeatAction.setCheckable(True)
        self.repeatAction.setChecked(True)
        self.playMode = QtGui.QMenu(self.trayIconMenu)
        self.playMode.setTitle(u"播放模式")
        self.playMode.addAction(self.shuffleAction)
        self.playMode.addAction(self.repeat1Action)
        self.playMode.addAction(self.repeatAction)

        self.trayIconMenu.addAction(self.playMode.menuAction())
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.aboutAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.activated.connect(self.trayIconActivated)
        self.trayIcon.show()

    def initMenu(self):
        """初始化菜单"""
        self.pop_menu = QtGui.QMenu(self.header)

        about_action = QAction(QIcon(""), u'关于', self)
        self.connect(about_action, SIGNAL("triggered()"), self.showAboutDialog)
        self.pop_menu.addAction(about_action)

        quit_action = QAction(QIcon(""), u'退出', self)
        self.connect(quit_action, SIGNAL("triggered()"), self.close)
        self.pop_menu.addAction(quit_action)
        self.pop_menu.setStyleSheet(_fromUtf8("color: rgb(255, 255, 255);"))

    def initData(self):
        """初始化数据"""
        self.songManager = SongManager('config/playerconfig.ini')
        self.connect(self, SIGNAL("add_from_drag(QStringList)"), self.addFromDrag)

        # 创建media
        self.song = Song()
        self.song.updateTime.connect(self.updateTime)
        self.song.playFinished.connect(self.playFinished)
        self.song.ircUpdate.connect(self.ircUpdate)
        # 绑定声音控件
        self.volume_slider.setAudioOutput(self.song.audio.audio_output)
        self.volume_slider.setMaximumVolume(1)
        # 绑定播放进度控件
        self.progress_slider.setMediaObject(self.song.audio.media_obj)

        # 装载默认歌曲列表
        path = self.refreshList()
        if path is None:
            path = u''
        self.path = QString(_fromUtf8(path))

    def playOrPause(self):
        """根据播放状态参数,确定点击效果
        如果正在播放则停止,并把按钮置为待播放状态
        如果已经停止则播放,并把按钮置为待停止状态"""
        # 设置play按钮状态
        if self.isPlaying:
            self.isPlaying = False
            self.setElementsStyle(self.btnplay, 'btnpause', True)
            self.btnplay.setToolTip(QString(u'<font color="#ffffff" size = 4>点击播放</font>'))
            self.song.pause()
            self.isPause = True
        else:
            self.isPlaying = True
            self.setElementsStyle(self.btnplay, 'btnplay', True)
            self.btnplay.setToolTip(QString(u'<font color="#ffffff" size = 4>点击暂停</font>'))

            if self.isPause:
                self.song.play()
            else:
                items = self.list_songs.selectedItems()
                if len(items) > 0:
                    item = self.list_songs.selectedItems()[0]
                    self.playIndex = self.list_songs.row(item)
                self.playByIndex(self.playIndex)

    def repeat(self):
        """循环播放(默认)"""
        self.shuffleAction.setChecked(False)
        self.repeatAction.setChecked(True)
        self.repeat1Action.setChecked(False)
        self.loop(False)
        self.shuffle(False)

    def loop(self, toggle=True):
        """单曲循环"""
        if self.isLoop or not toggle:
            self.isLoop = False
            self.setElementsStyle(self.btnloop, 'btnloop', True)
            self.shuffleAction.setChecked(False)
            self.repeatAction.setChecked(True)
            self.repeat1Action.setChecked(False)
        else:
            self.isLoop = True
            self.setElementsStyle(self.btnloop, 'btnloop::selection', True)
            self.shuffle(False)
            self.shuffleAction.setChecked(False)
            self.repeatAction.setChecked(False)
            self.repeat1Action.setChecked(True)

    def shuffle(self, toggle=True):
        """随机播放"""
        if self.isShuffle or not toggle:
            self.isShuffle = False
            self.setElementsStyle(self.btnshuffle, 'btnshuffle', True)
            self.shuffleAction.setChecked(False)
            self.repeatAction.setChecked(True)
            self.repeat1Action.setChecked(False)
        else:
            self.isShuffle = True
            self.setElementsStyle(self.btnshuffle, 'btnshuffle::selection', True)
            self.loop(False)
            self.shuffleAction.setChecked(True)
            self.repeatAction.setChecked(False)
            self.repeat1Action.setChecked(False)

    def playByShuffle(self):
        """随机播放方法"""
        index = random.randint(0, self.songManager.songCount - 1)
        self.playByIndex(index)
        self.list_songs.setCurrentRow(index)

    def playByLoop(self):
        """单曲循环方法"""
        self.playByIndex(self.playIndex)
        self.list_songs.setCurrentRow(self.playIndex)

    def musicPlay(self, e):
        """双击列表播放"""
        if len(self.list_songs.selectedItems()) == 0:
            return
        self.playIndex = self.list_songs.row(self.list_songs.selectedItems()[0])
        self.playByIndex(self.playIndex)
        self.list_songs.setCurrentRow(self.playIndex)

    def playNext(self):
        """播放下一首"""
        if self.isShuffle:
            self.playByShuffle()
            return
        self.playIndex += 1
        if self.playIndex >= self.songManager.songCount:
            self.playIndex = 0
        self.playByIndex(self.playIndex)
        self.list_songs.setCurrentRow(self.playIndex)

    def playPrev(self):
        """播放上一首"""
        self.playIndex -= 1
        if self.playIndex < 0:
            self.playIndex = self.songManager.songCount - 1
        self.playByIndex(self.playIndex)
        self.list_songs.setCurrentRow(self.playIndex)

    def playByIndex(self, index):
        """双击列表内歌曲进行播放"""
        url = self.songManager.getSong(index)
        self.song.url = url
        self.song.play()
        self.isPlaying = True
        songName = SongManager.getSongName(url)
        self.song_name.setText(songName)
        self.song_irc.setText('')
        self.setElementsStyle(self.btnplay, 'btnplay', True)
        self.btnplay.setToolTip(QString(u'<font color="#ffffff" size = 4>点击暂停</font>'))
        # 标题设置为歌名
        self.setWindowTitle(songName)
        self.trayIcon.setToolTip(songName)

    def stop(self):
        """停止播放"""
        self.song.stop()
        self.setElementsStyle(self.btnplay, 'btnpause', True)
        self.btnplay.setToolTip(QString(u'<font color="#ffffff" size = 4>点击播放</font>'))
        self.isPlaying = False
        self.consume_time.setText(tool.time_2_ms_str(0))

    def playFinished(self):
        """歌曲结束时调用方法"""
        if self.isLoop:
            self.playByLoop()
        elif self.isShuffle:
            self.playByShuffle()
        else:
            self.playNext()

    def ircUpdate(self, block):
        """更新歌词"""
        self.song_irc.setText(QtCore.QString.fromUtf8(block))
        self.desk_irc.setText(QtCore.QString.fromUtf8(block))

    def addFromDialog(self):
         """通过文件选择器添加歌曲,支持多选"""
         files = QFileDialog.getOpenFileNames(self, u"请选择歌曲", self.path, self.tr(songmanager.FILTER_FORMAT_STR))
         if len(files) > 0:
            self.path = QString.fromUtf8(os.path.split(files[0].__str__())[0])
         for file in files:
            result = self.songManager.addSong(file, QString.toUtf8(self.path))
            if result:
                self.list_songs.addItem(self.getFormatItem(file.__str__()))
                self.setButtonStates()

    def addFromDrag(self,QStringList):
         """通过拖动文件至列表添加歌曲,支持多选"""
         if len(QStringList) > 0:
            self.path = QString.fromUtf8(os.path.split(QStringList[0].__str__())[0])
         for file in QStringList:
            result = self.songManager.addSong(file, QString.toUtf8(self.path))
            if result:
                self.list_songs.addItem(self.getFormatItem(file.__str__()))
                self.setButtonStates()

    def getFormatItem(self, name):
        """得到格式化的列表Item"""
        item = [str(self.list_songs.count() + 1).rjust(5, ' '), SongManager.getSongName(name).__str__()]
        return (' ' * 4).join(item)

    def delete(self):
        """删除歌曲"""
        items = self.list_songs.selectedItems()
        indexlist = []
        for item in items:
            indexlist.append(self.list_songs.row(item))
        indexlist.sort(reverse=True)
        for index in indexlist:
            self.songManager.delSong(index, QString.toUtf8(self.path))
        self.refreshList()

    def hideWindows(self):
        """隐藏应用"""
        # self.song.stop()
        self.hide()

    def closeWindows(self):
        """关闭应用"""
        self.song.clear()
        self.close()

    def updateTime(self, time):
        """更新歌曲播放时间"""
        self.total_time.setText(tool.time_2_ms_str(self.song.audio.media_obj.totalTime()))
        self.consume_time.setText(tool.time_2_ms_str(time))

    def mouseMoveEvent(self, e):
        """拖拽窗口"""
        if e.buttons() & Qt.LeftButton:
            if hasattr(self, 'drag_pos'):
                self.move(e.globalPos() - self.drag_pos)
                e.accept()

    def mousePressEvent(self, e):
        """拖拽窗口"""
        if e.button() == Qt.LeftButton:
            self.drag_pos = e.globalPos() - self.frameGeometry().topLeft()
            e.accept()

    def contextMenuEvent(self, e):
        """上下文菜单"""
        self.pop_menu.exec_(e.globalPos())

    def showAboutDialog(self):
        """显示关于对话框"""
        self.about_dialog.show()

    def showOrDismissLyrics(self):
        """显示或隐藏歌词"""
        if not Lyrics_UI.show_lyrics:
            self.desk_irc.show()
            Lyrics_UI.show_lyrics = True
        else:
            self.desk_irc.desk_irc_close()

    def refreshList(self):
        """刷新列表"""
        path = self.songManager.loadList()
        self.list_songs.clear()
        if self.songManager.songCount == 0 :
            # 当没有歌曲时，设置按钮不可用
            self.song.stop()
            self.setButtonStates(False, False, False, False, False, False)
            self.setWindowTitle(u"音乐播放器")
            self.trayIcon.setToolTip(u"音乐播放器")
            return path
        for i in xrange(self.songManager.songCount):
            song = self.songManager.getSong(i)
            self.list_songs.addItem( self.list_songs.addItem(self.getFormatItem(song)))
        return path

    def setButtonStates(self, btnplay = True, btnstop = True, btnprev = True, btnnext = True, btnshuffle = True, btnloop = True):
        """设置按钮和拖动条状态"""
        self.btnplay.setEnabled(btnplay)
        self.btnstop.setEnabled(btnstop)
        self.btnprev.setEnabled(btnprev)
        self.btnnext.setEnabled(btnnext)
        self.btnshuffle.setEnabled(btnshuffle)
        self.btnloop.setEnabled(btnloop)

    def dragEnterEvent(self, event):
        """实现外部拖动添加歌曲"""
        if len(event.mimeData().urls()):
            self.dragFilesList = [file.toLocalFile() for file in event.mimeData().urls()]
            self.emit(SIGNAL("add_from_drag(QStringList)"), self.dragFilesList)
            event.accept()

    def trayIconActivated(self, reason):
        """系统托盘触发"""
        if reason == QtGui.QSystemTrayIcon.Trigger and \
                (self.isHidden() or self.isMinimized() or not self.isActiveWindow()):
            self.showNormal()
            self.show()
            self.activateWindow()

    def menuRequested(self, point):
        """列表右键菜单请求"""
        item = self.list_songs.itemAt(point)
        # 空白区域不显示菜单
        if item != None:
            self.rightMenuShow()

    def rightMenuShow(self):
        """列表右键菜单显示"""
        popMenu = QtGui.QMenu(self.list_songs)
        popMenu.addAction(QtGui.QAction(u'播放', self, triggered=self.musicPlay))
        popMenu.addAction(QtGui.QAction(u'下一首', self, triggered=self.playNext))
        popMenu.addAction(QtGui.QAction(u'添加', self, triggered = self.addFromDialog))
        popMenu.addAction(QtGui.QAction(u'删除', self, triggered = self.delete))
        popMenu.addAction(QtGui.QAction(u'全选', self, triggered=self.selectAll))
        popMenu.addAction(QtGui.QAction(u'打开目录', self, triggered=self.openFolder))
        popMenu.exec_(QtGui.QCursor.pos())

    def selectAll(self):
        """播放列表全选"""
        self.list_songs.selectAll()

    def openFolder(self):
        """打开文件所在目录"""
        item = self.list_songs.selectedItems()[0]
        songPath = self.songManager.getSong(self.list_songs.row(item))
        f = QFileInfo(_fromUtf8(songPath))
        try:
            QProcess.startDetached(
                "explorer.exe /select, " + f.filePath().replace("/", "\\").toUtf8().data().decode('utf-8'))
        except:
            QProcess.startDetached(
                "explorer.exe " + f.absolutePath().replace("/", "\\").toUtf8().data().decode('utf-8'))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    musicPlayer = MusicPlayer()
    musicPlayer.show()
    sys.exit(app.exec_())